package com.linkhub.oms.component.excel.listener;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.linkhub.oms.component.excel.annotation.RequiredProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;

import java.util.List;
import java.util.stream.Stream;

/**
 * @Description: BaseDataListener
 * @Author: echo
 * @Date: 2024/05/04 18:30
 * @Version: 1.0
 */
@Slf4j
public class BaseDataListener<T> implements ReadListener<T> {
    protected final List<T> list;

    public BaseDataListener(List<T> list) {
        this.list = list;
    }

    public List<T> acquireDataList() {
        return this.list;
    }

    @Override
    public void invoke(T data, AnalysisContext analysisContext) {
        if (checkEmptyField(data)) {
            log.warn("【{}】的第【{}】行被过滤，数据有空列", getSheetName(analysisContext), getRowIndex(analysisContext));
            return;
        }
        if (predicate(data)) {
            list.add(convertCellData(data));
        } else {
            log.warn("【{}】的第【{}】行被过滤，存在重复数据或其他不符合规则的数据", getSheetName(analysisContext), getRowIndex(analysisContext));
        }


    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("【{}】解析完成，共【{}】条数据", getSheetName(analysisContext), list.size());
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.error("【{}】的第【{}】行数据解析异常",
                getSheetName(context), getRowIndex(context), exception);
    }

    protected boolean predicate(T data) {
        return true;
    }

    protected T convertCellData(T data) {
        return data;
    }

    private String getSheetName(AnalysisContext analysisContext) {

        return analysisContext.readSheetHolder().getSheetName();
    }

    private Integer getRowIndex(AnalysisContext analysisContext) {
        return analysisContext.readSheetHolder().getRowIndex() + 1;
    }

    protected boolean checkEmptyField(T data) {
        return Stream.of(ReflectUtil.getFields(data.getClass()))
                .filter(field -> field.isAnnotationPresent(RequiredProperty.class))
                .anyMatch(field -> ObjectUtils.isEmpty(ReflectUtil.getFieldValue(data, field)));
    }
}
